package com.foreveross.crawl.adapter.sub.impl20140402.v3;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.util.EntityUtils;

import com.foreveross.crawl.adapter.AbstractAdapter;
import com.foreveross.crawl.adapter.PlaneInfoEntityBuilder;
import com.foreveross.crawl.domain.airfreight.AbstractPlaneInfoEntity;
import com.foreveross.crawl.domain.airfreight.CabinEntity;
import com.foreveross.crawl.domain.airfreight.doub.DoublePlaneInfoEntity;
import com.foreveross.crawl.domain.airfreight.doub.ReturnCabinEntity;
import com.foreveross.crawl.domain.airfreight.doub.ReturnDoublePlaneInfoEntity;
import com.foreveross.crawl.domain.airfreight.single.SinglePlaneInfoEntity;
import com.foreveross.crawl.exception.DirectFlightsNotFoundException;
import com.foreveross.crawl.exception.FlightInfoNotFoundException;
import com.foreveross.crawl.exception.NoTicketException;
import com.foreveross.taskservice.common.bean.TaskModel;

public class SiChuangAirAdapter extends AbstractAdapter {

	public SiChuangAirAdapter(TaskModel taskQueue) {
		super(taskQueue);

	}

	public static void main(String[] args) throws Exception {
		TaskModel taskQueue = new TaskModel();

		// taskQueue.setGrabChannelId(2L);
		taskQueue.setIsInternational(0);
		taskQueue.setFlightDate("2014-10-06");
		taskQueue.setReturnGrabDate("2014-11-07");
		taskQueue.setIsReturn(0);
		taskQueue.setFromCity("CAN");
		taskQueue.setToCity("CTU");
		SiChuangAirAdapter adapter = new SiChuangAirAdapter(taskQueue);
		Object obj = adapter.fetch("");
		List<Object> list = adapter.paraseToVo(obj);
		adapter.printJson(list, "f:/sichuang.txt");

	}

	@Override
	public Object fetch(String url) throws Exception {
		switch (super.getRouteType()) {
		case INTERNATIONAL_ROUND:
			return fetchInterRound();
		case INTERNATIONAL_ONEWAY:
			return fetchInterOneWay();
		case DOMESTIC_ONEWAYTRIP:
			return fetchDemoOneWay();
		}
		return null;
	}

	/**
	 * 进入国内单程
	 * 
	 * @return
	 * @throws Exception
	 */
	private Object fetchDemoOneWay() throws Exception {
		HttpPost p = null;
		String url;
		Map<String, String> params = new HashMap<String, String>();
		String page;
		JSONObject j;
		try {
			url = "http://www.scal.com.cn/B2C/ETicket/GetSingleChina";
			params.put("AVType", "0");
			params.put("OrgCity", taskQueue.getFromCity());
			params.put("OrgCityName", taskQueue.getFromCityName());
			params.put("DesCity", taskQueue.getToCity());
			params.put("DesCityName", taskQueue.getToCityName());
			params.put("BuyerType", "0");
			params.put("CardFlag", "");
			params.put("Flag", "null");
			params.put("FlightDate", taskQueue.getFlightDate());
			params.put("IsFixedCabin", "false");
			params.put("PassKey", "3807208448F077E4FBC633AAA6AB2320");
			params.put("RouteIndex", "1");
			params.put("AirlineType", "Single");
			params.put("RouteName", "单    程");

			p = super.getBasePost(url, params);
			this.setDefaultHeadValue(p);
			page = this.excuteRequestAndRecord(p);
			j = JSONObject.fromObject(page);
		} finally {
			page = null;
			params.clear();
			params = null;
			url = null;
			if (p != null) {
				p.releaseConnection();
			}
		}
		return j;
	}

	/**
	 * 执行连接和记录
	 * 
	 * @param request
	 * @return
	 * @throws Exception
	 */
	private String excuteRequestAndRecord(HttpRequestBase request)
			throws Exception {
		HttpClient h;
		String page;
		try {
			h = super.getHttpClient();
			page = EntityUtils.toString(h.execute(request).getEntity());
//			super.setLenghtCount( page.length());
			super.appendPageContents(page);
		} finally {
			h = null;
		}
		return page;
	}

	/**
	 * 进入国际单程
	 * 
	 * @return
	 * @throws Exception
	 */
	private Object fetchInterOneWay() throws Exception {

		HttpPost p = null;
		String url;
		Map<String, String> params = new HashMap<String, String>();
		String page;
		JSONObject j;
		try {
			url = "http://www.scal.com.cn/B2C/ETicket/GetInterSingleChina";
			params.put("BuyerType", "0");
			params.put("OrgCity", taskQueue.getFromCity());
			params.put("OrgCityName", taskQueue.getFromCityName());
			params.put("DesCity", taskQueue.getToCity());
			params.put("DesCityName", taskQueue.getToCityName());
			params.put("Flag", "null");
			params.put("FlightDate", taskQueue.getFlightDate());
			params.put("IsFixedCabin", "false");
			params.put("PassKey", "3807208448F077E4FBC633AAA6AB2320");
			params.put("RouteIndex", "1");
			params.put("SingleOrMore", "1");
			p = super.getBasePost(url, params);
			this.setDefaultHeadValue(p);
			page = this.excuteRequestAndRecord(p);
			j = JSONObject.fromObject(page);
		} finally {
			page = null;
			params.clear();
			params = null;
			url = null;
			if (p != null) {
				p.releaseConnection();
			}
		}
		return j;
	}

	/**
	 * 进入国际往返
	 * 
	 * @return
	 * @throws Exception
	 */
	private Object fetchInterRound() throws Exception {
		HttpClient h;
		HttpPost p = null;
		String url;
		Map<String, String> params = new HashMap<String, String>();
		String page;
		JSONObject j;
		try {
			h = super.getHttpClient();
			url = "http://www.scal.com.cn/B2C/ETicket/GetInterSingleChina";
			params.put("BuyerType", "0");
			params.put("OrgCity", taskQueue.getFromCity());
			params.put("OrgCityName", taskQueue.getFromCityName());
			params.put("DesCity", taskQueue.getToCity());
			params.put("DesCityName", taskQueue.getToCityName());
			params.put("Flag", "null");
			params.put("FlightDate", taskQueue.getFlightDate());
			params.put("IsFixedCabin", "false");
			params.put("IsRound", "true");
			params.put("PassKey", "3807208448F077E4FBC633AAA6AB2320");
			params.put("ROrgCity", taskQueue.getToCity());
			params.put("RDesCity", taskQueue.getFromCity());
			params.put("RFlightDate", taskQueue.getReturnGrabDate());
			params.put("RouteIndex", "1");
			/* params.put("RouteName","去 程"); */
			params.put("SingleOrMore", "5");
			p = super.getBasePost(url, params);
			setDefaultHeadValue(p);
			page = EntityUtils.toString(h.execute(p).getEntity());
			if (page != null) {
				super.setLenghtCount(page.length());
				super.appendPageContents(page);
			}
			j = JSONObject.fromObject(page);
		} finally {
			page = null;
			params.clear();
			params = null;
			url = null;
			if (p != null) {
				p.releaseConnection();
			}
			h = null;
		}
		return j;
	}

	private void setDefaultHeadValue(HttpRequestBase request) throws Exception {
		Map<String, String> headValue = new HashMap<String, String>();
		headValue.put("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");
		headValue.put("Host", "www.scal.com.cn");
		headValue.put("Pragma", "no-cache");
		/*
		 * headValue.put("Referer",
		 * "http://www.scal.com.cn/B2C/ETicket/InterAirlineList");
		 */
		/*
		 * headValue.put("Referer",
		 * "http://www.scal.com.cn/B2C/ETicket/AirlineList");
		 */
		headValue
				.put("User-Agent",
						"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:25.0) Gecko/20100101 Firefox/25.0");
		headValue.put("X-Requested-With", "XMLHttpRequest");
		/* headValue.put("", ""); */
		super.setRequestHead(request, headValue);
	}

	@Override
	public List<Object> paraseToVo(Object obj) throws Exception {
		switch (super.getRouteType()) {
		case INTERNATIONAL_ONEWAY:
			return paraseInterOneWay(obj);
		case INTERNATIONAL_ROUND:
			return paraseInterRound(obj);
		case DOMESTIC_ONEWAYTRIP:
			return paraseDomeOneWay(obj);
		default:
			return null;
		}

	}

	private List<Object> paraseDomeOneWay(Object obj) throws Exception {
		List<Object> result = new ArrayList<Object>();
		JSONObject j;
		JSONArray flights;
		JSONObject f;
		JSONArray cs;
		JSONObject c;
		SinglePlaneInfoEntity singleEntity;
		CabinEntity cabinEntity;
		try {
			if(obj.toString().contains("查询当日无航班!")){rollbackProxyIp(true); throw new NoTicketException("查询日期没有航班！");}
			if (((JSONObject) obj).get("AirlineListJSON") != null) {
				j = JSONObject.fromObject(((JSONObject) obj)
						.get("AirlineListJSON"));
				flights = j.getJSONArray("FlightList");
				for (int i = 0; i < flights.size(); i++) {
					f = flights.getJSONObject(i);
					double taxesPrice = f.getDouble("AirTax")
							+ f.getDouble("AddFare");
					singleEntity = PlaneInfoEntityBuilder.buildPlaneInfo(
							taskQueue, f.getString("FlightNO").substring(0, 2),
							"川航", "四川航空", f.getString("TakeOffTimeShort"),
							f.getString("ArriveTimeShort"),
							f.getString("FlightNO"), null, null, null,
							f.getString("PlaneModel"), null, null, taxesPrice
									+ "", taxesPrice + "",
							SinglePlaneInfoEntity.class);
					if (f.get("CabinList") != null) {
						cs = f.getJSONArray("CabinList");
						for (int ii = 0; ii < cs.size(); ii++) {
							c = cs.getJSONObject(ii);
							cabinEntity = PlaneInfoEntityBuilder
									.buildCabinInfo(
											c.getString("CabinName"),
											c.getString("CabinNO"),
											null,
											null,
											c.getString("RealPrice"),
											null,
											c.getString("CabinRuleDescription"),
											c.getString("Amount"),
											CabinEntity.class);
							String cabinRebate = c.getString("CabinRebate");
							double rebate = cabinRebate == null
									|| !cabinRebate.contains("折") ? 0.0
									: Double.parseDouble(cabinRebate.substring(
											0, cabinRebate.lastIndexOf("折") - 1)) * 0.1;
							cabinEntity.setRebate(rebate);
							cabinEntity.setTaxesPrice(taxesPrice);
							cabinEntity.setOriginalPrice(cabinEntity.getPrice()
									+ taxesPrice);
							setEntityLowestPrice(singleEntity,
									c.getDouble("RealPrice"));
							setEntityHightPrice(singleEntity,
									c.getDouble("RealPrice"));
							singleEntity.getCabins().add(cabinEntity);
						}
					}
					if (f.get("CabinModel") != null) {
						c = f.getJSONObject("CabinModel");
						cabinEntity = PlaneInfoEntityBuilder.buildCabinInfo(
								c.getString("CabinName"),
								c.getString("CabinNO"), null, null,
								c.getString("RealPrice"), null,
								c.getString("CabinRuleDescription"),
								c.getString("Amount"), CabinEntity.class);
						cabinEntity.setTaxesPrice(taxesPrice);
						cabinEntity.setOriginalPrice(c.getDouble("RealPrice")
								+ taxesPrice);
						setEntityLowestPrice(singleEntity,
								c.getDouble("RealPrice"));
						setEntityHightPrice(singleEntity,
								c.getDouble("RealPrice"));
						singleEntity.getCabins().add(cabinEntity);
					}
					singleEntity.setSumHighestPrice(singleEntity
							.getTotalHighestPrice()
							+ singleEntity.getTotalHighestTaxesPrice());
					singleEntity.setSumLowestPrice(singleEntity
							.getTotalLowestPrice()
							+ singleEntity.getTotalLowestTaxesPrice());
					result.add(singleEntity);
				}
			}

			if (((JSONObject) obj).get("AirlineList") != null
					&& result.isEmpty()) {
				throw new DirectFlightsNotFoundException();
			}
		} finally {
			j = null;
			flights = null;
			f = null;
			cs = null;
			c = null;
			singleEntity = null;
			cabinEntity = null;
		}
		rollbackProxyIp(true);
		return result;
	}

	// /**
	// *中转归类，每一个代表一系列的航班，连成的整个信息
	// * @param <T>
	// * @param list
	// * @return
	// */
	// private <T> List<List<JSONObject>> transClassify(Object obj){
	// List<List<JSONObject>> list=new ArrayList<List<JSONObject>>();
	// Map<Integer,List<JSONObject>> temp=new
	// HashMap<Integer,List<JSONObject>>();
	// JSONArray arry=JSONArray.fromObject(obj);
	// for(int i=0;i<arry.size();i++){
	// int
	// j=arry.getJSONObject(i).getJSONArray("FlightList").getJSONObject(0).getInt("FlightIndex");
	// if(!temp.containsKey(j)){
	// temp.put(j, new ArrayList<JSONObject>());
	// }
	// temp.get(j).add(arry.getJSONObject(i));
	// }
	// //对每一组按时间排序
	// Iterator<Entry<Integer, List<JSONObject>>> it=temp.entrySet().iterator();
	// Entry<Integer, List<JSONObject>> en=null;
	// while(it.hasNext()){
	// //yyyy-MM-ddHH:mm
	// en=it.next();
	// Collections.sort(en.getValue(),new ExpandComparator("yyyy-MM-ddHH:mm"));
	// list.add(en.getValue());
	// }
	// return list;
	// }

	private List<Object> paraseInterOneWay(Object obj) throws Exception {

		List<Object> result = null;
		JSONObject j;
		JSONObject temp;
		List<SinglePlaneInfoEntity> singleEntitys = null;
		try {
			j = (JSONObject) obj;
			j = JSONObject.fromObject(j.get("AirlineListJSON"));
			temp = j.getJSONObject("FlightInfo");
			if (temp.isArray()) {
				singleEntitys = this._paraseEntity(
						j,
						j.getJSONObject("AirlineListJSON").getJSONArray(
								"FlightInfo"), SinglePlaneInfoEntity.class);// 去程航班
			} else {
				singleEntitys = this._paraseEntity(j,
						JSONArray.fromObject("[" + temp.toString() + "]"),
						SinglePlaneInfoEntity.class);// 去程航班
			}
			if (singleEntitys != null && !singleEntitys.isEmpty()) {
				result = Arrays.asList(singleEntitys.toArray());
			}
		} finally {
			j = null;
		}
		return result;

	}

	/**
	 * 解析国际往返
	 * 
	 * @param obj
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unused")
	private List<Object> paraseInterRound(Object obj) throws Exception {
		List<Object> result = new ArrayList<Object>();
		JSONObject j;
		JSONObject temp;
		DoublePlaneInfoEntity doubleEntity;
		List<DoublePlaneInfoEntity> doubleEntitys = null;
		List<ReturnDoublePlaneInfoEntity> reDoubleEntitys = null;
		try {
			j = (JSONObject) obj;
			j = JSONObject.fromObject(j.get("AirlineListJSON"));
			temp = j.getJSONObject("FlightInfo");
			if (temp.isArray()) {
				doubleEntitys = this._paraseEntity(null,
						j.getJSONArray("FlightInfo"),
						DoublePlaneInfoEntity.class);// 去程航班
			} else {
				doubleEntitys = this._paraseEntity(null,
						JSONArray.fromObject("[" + temp.toString() + "]"),
						DoublePlaneInfoEntity.class);// 去程航班
			}
			temp = j.getJSONObject("ReturnFlightInfo");
			if (temp.isArray()) {
				reDoubleEntitys = this._paraseEntity(null,
						j.getJSONArray("ReturnFlightInfo"),
						ReturnDoublePlaneInfoEntity.class);// 去程航班
			} else {
				reDoubleEntitys = this._paraseEntity(null,
						JSONArray.fromObject("[" + temp.toString() + "]"),
						ReturnDoublePlaneInfoEntity.class);// 去程航班
			}
			// 阶乘
			for (DoublePlaneInfoEntity d : doubleEntitys) {
				d.getReturnPlaneInfos().addAll(reDoubleEntitys);
				result.add(d);
			}
		} finally {
			j = null;
			doubleEntity = null;
			doubleEntitys = null;
			reDoubleEntitys = null;
		}
		return result;
	}

	/**
	 * 根绝一段json解析实体
	 * 
	 * @param array
	 * @param c
	 * @return
	 * @throws Exception
	 */
	private <T extends AbstractPlaneInfoEntity> List<T> _paraseEntity(
			JSONObject root, JSONArray array, Class<T> clzz) throws Exception {
		List<T> result = new ArrayList<T>();
		JSONObject f;
		JSONObject c;
		T t;
		CabinEntity cabinEntity;
		ReturnCabinEntity reCabinEntity;
		try {
			for (int i = 0; i < array.size(); i++) {
				f = array.getJSONObject(i);
				t = PlaneInfoEntityBuilder.buildPlaneInfo(taskQueue, f
						.getString("FlightNo").substring(0, 2), "川航", "四川航空", f
						.getString("TakeOffTime").split(" ")[1].trim()
						.substring(0, 5),
						f.getString("ArriveTime").split(" ")[1].trim()
								.substring(0, 5), f.getString("FlightNo"),
						null, null, null, null,null,null,null,f.getString("PlaneModel"), clzz);
				c = f.get("CurrentCabins") != null ? f
						.getJSONObject("CurrentCabins") : (root == null
						|| root.get("CurrentCabins") == null ? null : root
						.getJSONObject("CurrentCabins"));
				if (c != null) {
					String price = null;
					if (c.get("ADBasePrice") != null) {
						price = c.getString("ADBasePrice");
					} else if (c.get("ADToalPrice") != null) {
						price = c.getString("ADToalPrice");
					}
					if (SinglePlaneInfoEntity.class.equals(clzz)) {
						cabinEntity = PlaneInfoEntityBuilder.buildCabinInfo(
								c.getString("CabinName"),
								c.getString("CabinsNO"), null, price, price,
								c.getString("ADRule"), null, CabinEntity.class);
						((SinglePlaneInfoEntity) t).getCabins()
								.add(cabinEntity);
						setEntityLowestPrice(t, cabinEntity.getPrice());
						setEntityHightPrice(t, cabinEntity.getPrice());
					} else if (DoublePlaneInfoEntity.class.equals(clzz)) {
						cabinEntity = PlaneInfoEntityBuilder.buildCabinInfo(
								c.getString("CabinName"),
								c.getString("CabinsNO"), null, price, price,
								c.getString("ADRule"), null, CabinEntity.class);
						((DoublePlaneInfoEntity) t).getCabins()
								.add(cabinEntity);
						setEntityLowestPrice(t, cabinEntity.getPrice());
						setEntityHightPrice(t, cabinEntity.getPrice());
					} else if (ReturnDoublePlaneInfoEntity.class.equals(clzz)) {
						reCabinEntity = PlaneInfoEntityBuilder.buildCabinInfo(
								c.getString("CabinName"),
								c.getString("CabinsNO"), null, price, price,
								c.getString("ADRule"), null,
								ReturnCabinEntity.class);
						((ReturnDoublePlaneInfoEntity) t).getReturnCabins()
								.add(reCabinEntity);
						setEntityLowestPrice(t, reCabinEntity.getPrice());
						setEntityHightPrice(t, reCabinEntity.getPrice());
					}

				}
				result.add(t);
			}
		} finally {

		}
		return result;
	}

	private void setEntityLowestPrice(AbstractPlaneInfoEntity entity,
			Double price) {
		if (entity == null || price == null) {
			return;
		}
		entity.setTotalLowestPrice(entity.getTotalLowestPrice() == null ? price
				: Math.min(entity.getTotalLowestPrice(), price));
	}

	private void setEntityHightPrice(AbstractPlaneInfoEntity entity,
			Double price) {
		if (entity == null || price == null) {
			return;
		}
		entity.setTotalHighestPrice(entity.getTotalHighestPrice() == null ? price
				: Math.max(entity.getTotalHighestPrice(), price));
	}

	@Override
	public String getUrl() throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	private int errorCount = 0;

	@Override
	public boolean validateFetch(Object obj) throws Exception {
		if (obj == null) {
			throw new Exception("源数据为空");
		}
		if (obj.toString().matches(".*查询当日无航班.*")) {
			throw new FlightInfoNotFoundException();
		}
		if (obj.toString().matches(".*系统繁忙！请稍候重试.*")) {
			errorCount++;
			if (errorCount >= 3) {
				throw new FlightInfoNotFoundException();
			}
		}
		if (obj.toString().matches(".*\"Result\":false.*")) {
			throw new Exception("json返回信息错误 Result=false");
		}
		return true;
	}

}
